package cn.buk.tms.train.service;

import cn.buk.common.JsonResult;
import cn.buk.tms.dto.TrainRefundOrderDto;
import cn.buk.qms.service.BaseAbstractService;
import cn.buk.tms.entity.bill.BillInfo;
import cn.buk.tms.entity.misc.*;
import cn.buk.tms.entity.order.OrderNoInfo;
import cn.buk.tms.entity.order.train.TrainOrder;
import cn.buk.tms.entity.order.train.TrainRefundOrder;
import cn.buk.tms.train.dao.TrainOrderDao;
import cn.buk.tms.train.dao.TrainRefundOrderDao;
import cn.buk.tms.train.sc.TrainOrderSearchCriteria;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author yfdai
 */
@Component
public class TrainRefundOrderServiceImpl extends BaseAbstractService implements TrainRefundOrderService {

    private static final Logger logger = LogManager.getLogger(TrainRefundOrderServiceImpl.class);

    @Autowired
    private TrainRefundOrderDao dao;

    @Autowired
    private TrainOrderDao trainOrderDao;

    /**
     * 搜索订单
     * @param enterpriseId
     * @param sc
     * @return
     */
    @Override
    public List<TrainRefundOrderDto> searchOrders(int enterpriseId, int userId, TrainOrderSearchCriteria sc) {
        List<Integer> allowedCustomerIds = searchAllowedCustomerIds(enterpriseId, userId);

        User user = userDao.getUserById(userId);
        final String username = user.getUsername();

        if(isOnlySeeOwn(enterpriseId, userId)) {
            //只能看自己的订单
            sc.setOp1(username);
        }

        List<TrainRefundOrder> orders = dao.searchOrders(enterpriseId, sc, allowedCustomerIds);

        final boolean needHideCustomerName = isNeedHideCustomerName(enterpriseId, userId);

        List<TrainRefundOrderDto> dtos = new ArrayList<>();
        for(TrainRefundOrder order: orders) {
            maskCustomerName(order.getCustomer(), order.getOperator(), user.getUsername(), needHideCustomerName);

            dtos.add(TrainRefundOrderDto.createByOrder(order));
        }

        return dtos;
    }


    /**
     * 获取订单详情
     * @param enterpriseId
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public TrainRefundOrderDto getOrderById(final int enterpriseId, int userId, final int orderId) {
        TrainRefundOrder o = dao.getOrderById(orderId);

        if (o == null || o.getEnterpriseId() != enterpriseId) {
          return null;
        } else {
            //是否要对当前用户隐藏客户名称
            if (isNeedHideCustomerName(enterpriseId, userId)) {
                User user = userDao.getUserById(userId);
                maskCustomerName(o.getCustomer(), o.getOperator(), user.getUsername(), true);
            }
            return TrainRefundOrderDto.createByOrder(o);
        }
    }

    /**
     * 创建订单
     * @param enterpriseId
     * @param dto
     * @return
     */
    @Override
    public JsonResult createOrder(final int enterpriseId, final String username, TrainRefundOrderDto dto) {
//        dto.processPassengerInfo();
//        try {
//            ValidationUtils.validate(dto);
//            for(TrainOrderPassengerDto psgDto: dto.getPassengers()) {
//                ValidationUtils.validate(psgDto);
//            }
//        } catch (Exception e) {
//            logger.error(e.getMessage());
//            return JsonResult.createJsonResult(-1, e.getMessage());
//        }

        dto.setEnterpriseId(enterpriseId);
        dto.setOperator(username);

        //从火车票订单中获取需要的信息
        if (dto.getTrainOrderNo() != null && dto.getTrainOrderNo().trim().length() > 0) {
            TrainOrder trainOrder = trainOrderDao.getTrainOrderByOrderNo(enterpriseId, dto.getTrainOrderNo());
            if (trainOrder != null) {
                dto.setSupplierId(trainOrder.getSupplier().getId());
                dto.setPaymentMethodId(trainOrder.getPaymentMethod().getId());

                dto.setCustomerId(trainOrder.getCustomerId());
                dto.setCostCenter(trainOrder.getCostCenter());
                dto.setProjectName(trainOrder.getProjectName());
            }
        }

        TrainRefundOrder trainOrder = TrainRefundOrderDto.convertToOrder(dto);

        // 订单号
        trainOrder.setOrderNo(orderNoGenerator.generateOrderNo(enterpriseId, OrderNoInfo.ORDER_TRAIN_REFUND));

        try {
            int retCode = dao.createOrder(trainOrder);
            return JsonResult.createJsonResult(retCode);
        } catch (RuntimeException ex) {
            logger.error(ex.getMessage());
            return JsonResult.createJsonResult(-100, ex.getMessage());
        }
    }

    /**
     * 修改酒店订单的备注
     * @param enterpriseId
     * @param username
     * @param orderId
     * @param remark
     * @return
     */
    @Override
    public JsonResult updateOrderRemark(int enterpriseId, String username, int orderId, String remark) {
        try {
            int retCode = dao.updateOrderRemark(enterpriseId, username, orderId, remark);
            return JsonResult.createJsonResult(retCode);
        } catch (RuntimeException ex) {
            return JsonResult.createJsonResult(-100, ex.getMessage());
        }
    }

    @Override
    public JsonResult updateOrderExternalOrderNo(int enterpriseId, String username, int orderId, String externalOrderNo) {
        try {
            int retCode = dao.updateOrderExternalOrderNo(enterpriseId, username, orderId, externalOrderNo);
            return JsonResult.createJsonResult(retCode);
        } catch (RuntimeException ex) {
            return JsonResult.createJsonResult(-100, ex.getMessage());
        }
    }



    /**
     * 修改酒店订单的价格
     * @param enterpriseId
     * @param username
     * @param orderId
     * @param price
     * @param cost
     * @param serviceCharge
     * @return
     */
    @Override
    public JsonResult updateOrderPrice(int enterpriseId, String username, int orderId, double price, double cost, double serviceCharge) {
        TrainRefundOrder trainOrder = dao.getOrderById(orderId);
        if (trainOrder.getStatus() == TrainOrder.STATUS_DONE || trainOrder.getStatus() == TrainOrder.STATUS_CANCELED) {
            return JsonResult.createJsonResult(-1, "价格已不能修改");
        }

        TrainRefundOrderDto dto = TrainRefundOrderDto.createByOrder(trainOrder);
        dto.setPrice(price);
        dto.setCost(cost);
        dto.setServiceCharge(serviceCharge);
        dto.calc();

        int retCode = dao.updateOrderPrice(enterpriseId, username, orderId, price, cost, serviceCharge,
                dto.getTotalAmount(), dto.getTotalCost(), dto.getProfit());
        return JsonResult.createJsonResult(retCode);
    }


    /**
     * 开始处理订单
     * @param enterpriseId
     * @param username
     * @param orderId
     * @return
     */
    @Override
    public JsonResult processOrder(int enterpriseId, String username, int orderId) {
        try {
            int retCode = dao.processOrder(enterpriseId, username, orderId);
            return JsonResult.createJsonResult(retCode);
        } catch (RuntimeException ex) {
            return JsonResult.createJsonResult(-100, ex.getMessage());
        }
    }

    /**
     * 火车票订单处理完毕
     * @param enterpriseId
     * @param username
     * @param orderId
     * @param remark
     * @return
     */
    @Override
    public JsonResult finishOrder(int enterpriseId, String username, int orderId, String remark) {

        int retCode = 0;
        try {
            retCode = dao.finishOrder(enterpriseId, username, orderId, remark);
        } catch (RuntimeException ex) {
            return JsonResult.createJsonResult(-100, ex.getMessage());
        }

        if (retCode == 1) {
            //导入账单
            importService.importTrainRefundOrder(enterpriseId, username, orderId);
        }

        return JsonResult.createJsonResult(retCode);
    }

    @Override
    public List<OperationLog> searchOrderHistory(int enterpriseId, int orderId) {
        return dao.searchOrderHistory(enterpriseId, orderId);
    }

    /**
     * 取消酒店订单
     * @param enterpriseId
     * @param username
     * @param orderId
     * @param remark
     * @return
     */
    @Override
    public JsonResult cancelOrder(int enterpriseId, String username, int orderId, String remark) {
        try {
            int retCode = dao.cancelOrder(enterpriseId, username, orderId, remark);
            return JsonResult.createJsonResult(retCode);
        } catch (RuntimeException ex) {
            return JsonResult.createJsonResult(-100, ex.getMessage());
        }
    }

    /**
     * 回滚酒店订单的状态
     * @param enterpriseId
     * @param username
     * @param orderId
     * @return
     */
    @Override
    @Secured({RoleInfo.ROLE_ADMIN, RoleInfo.ROLE_SUPERVISOR})
    public JsonResult rollbackOrder(final int enterpriseId, final String username, final int orderId, final String remark) {
        if (remark == null || remark.trim().length() < 2) {
          return JsonResult.createJsonResult(-10, "请输入理由");
        }

        TrainRefundOrder trainOrder = dao.getOrderById(orderId);
        if (trainOrder == null || trainOrder.getEnterpriseId() != enterpriseId) {
            return JsonResult.createJsonResult(-1, "订单不存在");
        }

        if (trainOrder.getStatus() != TrainOrder.STATUS_DONE) {
            return JsonResult.createJsonResult(-2, "订单状态不是完成状态。");
        }

        List<BillInfo> billInfos = billService.searchBillInfoByOrderNo(enterpriseId, trainOrder.getOrderNo());
        if (!billInfos.isEmpty()) {
            doSendAlert(enterpriseId, "订单(" + trainOrder.getOrderNo() + ")回滚失败，存在对应的账单", null, EntDepartment.DEPT_ADMINISTRATOR);
            return JsonResult.createJsonResult(-2, "存在对应的账单，不能回滚");
        }

        int retCode = dao.rollbackOrder(enterpriseId, username, orderId, remark);
        if (retCode > 0) {
            doSendAlert(enterpriseId, "火车票订单(" + trainOrder.getOrderNo() + ")已回滚: " + remark, null, EntDepartment.DEPT_ADMINISTRATOR);
        }

        return JsonResult.createJsonResult(retCode);
    }



  @Override
  public void autoAlertOrderStatus() {
      final int enterpriseId = 5;
      TrainOrderSearchCriteria sc = new TrainOrderSearchCriteria();
      sc.setStatus(0);
      sc.setPageSize(1000);

      List<TrainRefundOrder> orders = dao.searchOrders(enterpriseId, sc, null);

      if (!orders.isEmpty()) {
          doSendAlert(enterpriseId, "有" + orders.size() + "个火车票退票单待处理", null, EntDepartment.DEPT_TICKETING);
      }
  }

}
